﻿using System;
using DotNetNuke.Entities.Modules;
using DotNetNuke.Services.Exceptions;
using System.Net;
using System.Collections.Generic;
using ITM.Modules.SharePointFileExplorer.WSWebs;
using System.Xml;
using ITM.Modules.SharePointFileExplorer.SharePoint;
using Telerik.Web.UI;

namespace ITM.Modules.SharePointFileExplorer
{
    public partial class Settings : ModuleSettingsBase
    {
        // constant strings
        private const string WEBS = @"_vti_bin/Webs.asmx";
        private const string SKIN = "Telerik";
        public override void LoadSettings()
        {
            try
            {
                if (!IsPostBack)
                {
                    tvUrls.Skin = SKIN;
                    // load previous settings
                    // new ModuleController().DeleteModuleSettings(this.ModuleId);
                    object objUserName = ModuleSettings["SP_USERNAME"];
                    object objPassword = ModuleSettings["SP_PASSWORD"];
                    object objDomain = ModuleSettings["SP_DOMAIN"];
                    object objMainUrl = ModuleSettings["SP_MAINURL"];
                    object objInputUrl = ModuleSettings["SP_INPUTURL"];
                    object objSelectedUrl = ModuleSettings["SP_SELECTEDURL"];
                    if (objUserName != null)
                        tbUserName.Text = objUserName.ToString();
                    if (objPassword != null)
                        tbPassword.Attributes["Value"] = objPassword.ToString();
                    if (objDomain != null)
                        tbDomain.Text = objDomain.ToString();
                    if (objMainUrl != null)
                        tbSPMainUrl.Text = objMainUrl.ToString();
                    if (objInputUrl != null)
                        tbInputSPUrl.Text = objInputUrl.ToString();
                    // A trick here
                    if (objUserName != null && objPassword != null && objDomain != null && objMainUrl != null)
                    {
                        NetworkCredential networkCredential = new NetworkCredential((string)objUserName, (string)objPassword, (string)objDomain);
                        BuildTree((string)objMainUrl, networkCredential);
                        panelExistingUrls.Visible = true;
                        tvUrls.ExpandAllNodes();
                        if (objSelectedUrl != null)
                        {
                            if (tvUrls.FindNodeByValue(objSelectedUrl.ToString()) != null)
                                tvUrls.FindNodeByValue(objSelectedUrl.ToString()).ForeColor = System.Drawing.Color.DeepSkyBlue;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Exceptions.ProcessModuleLoadException(this, ex);
            }
        }

        public override void UpdateSettings()
        {
            try
            {
                ModuleController controller = new ModuleController();
                controller.UpdateModuleSetting(this.ModuleId, "SP_USERNAME", GetUserName());
                controller.UpdateModuleSetting(this.ModuleId, "SP_PASSWORD", GetPassword());
                controller.UpdateModuleSetting(this.ModuleId, "SP_DOMAIN", GetDomain());
                controller.UpdateModuleSetting(this.ModuleId, "SP_MAINURL", GetMainUrl());
                tbPassword.Attributes.Add("Value", GetPassword());

                if (panelExistingUrls.Visible)
                    controller.UpdateModuleSetting(this.ModuleId, "SP_SELECTEDURL", tvUrls.SelectedNode.Value);
                else if (panelInputUrl.Visible)
                    controller.UpdateModuleSetting(this.ModuleId, "SP_SELECTEDURL", tbInputSPUrl.Text.ToString());
            }
            catch (Exception ex)
            {
                Exceptions.ProcessModuleLoadException(this, ex);
            }
        }

        /// <summary>
        /// Get subsites of a specific site
        /// </summary>
        /// <param name="hostUrl"></param>
        /// <param name="networkCredential"></param>
        /// <returns>dictionary<siteTitle, siteUrl></returns>
        private Dictionary<string, string> GetWebCollection(string hostUrl, NetworkCredential networkCredential)
        {
            Dictionary<string, string> subWebs = new Dictionary<string, string>();
            if (!hostUrl.EndsWith("/"))
                hostUrl += "/";
            try
            {
                Webs WebsService = new Webs
                {
                    Url = hostUrl + WEBS,
                    Credentials = networkCredential
                };
                XmlNode webCollection = WebsService.GetWebCollection();
                XmlNodeList webList = webCollection.SelectNodes("*");
                foreach (XmlNode web in webList)
                {
                    subWebs.Add(web.Attributes["Title"].Value, web.Attributes["Url"].Value);
                }
                return subWebs;
            }
            catch
            {
                throw;
            }
        }

        /// <summary>
        /// Check whether a specific site has document libraries or not
        /// </summary>
        /// <param name="networkCredential"></param>
        /// <param name="sharepointUrl"></param>
        /// <returns>number of document libraries</returns>
        private int HasDocumentLibraries(NetworkCredential networkCredential, string sharepointUrl)
        {
            try
            {
                SharePointController sharepointController = new SharePointController(networkCredential, sharepointUrl);
                return sharepointController.SPGetDocumentLibraries().Count;
            }
            catch
            {
                throw;
            }
        }

        /// <summary>
        /// Build root node for treeview
        /// </summary>
        /// <param name="sharepointUrl"></param>
        private void BuildTree(string sharepointUrl, NetworkCredential networkCredential)
        {
            tvUrls.Nodes.Clear();
            var rootNode = new RadTreeNode();
            rootNode.Text = sharepointUrl + "(" + HasDocumentLibraries(networkCredential, sharepointUrl).ToString() + ")";
            rootNode.ImageUrl = "Images/spSiteIcon.png";
            rootNode.Value = sharepointUrl;
            tvUrls.Nodes.Add(rootNode);
            BuildUrls(rootNode, sharepointUrl, networkCredential);
        }

        /// <summary>
        /// Build Url node for treeview
        /// </summary>
        /// <param name="parentNode"></param>
        /// <param name="sharepointUrl"></param>
        /// <param name="networkCredential"></param>
        private void BuildUrls(RadTreeNode parentNode, string sharepointUrl, NetworkCredential networkCredential)
        {
            Dictionary<string, string> subWebs = GetWebCollection(sharepointUrl, networkCredential);
            foreach (var subWeb in subWebs)
            {
                var webNode = new RadTreeNode();
                webNode.Text = subWeb.Key.ToString() + "(" + HasDocumentLibraries(networkCredential, subWeb.Value.ToString()).ToString() + ")";
                webNode.Value = subWeb.Value.ToString();
                webNode.ImageUrl = "Images/spSiteIcon.png";
                parentNode.Nodes.Add(webNode);
                BuildUrls(webNode, subWeb.Value.ToString(), networkCredential);
            }
        }

        protected void btnGetWebCollection_OnClick(object sender, EventArgs e)
        {
            try
            {
                string username = GetUserName();
                string password = GetPassword();
                string domain = GetDomain();
                string mainUrl = GetMainUrl();
                NetworkCredential networkCredential = new NetworkCredential(username, password, domain);
                BuildTree(mainUrl, networkCredential);
                panelExistingUrls.Visible = true;
                if (panelErrorMessageLog.Visible)
                    panelErrorMessageLog.Visible = false;
            }
            catch (Exception ex)
            {
                panelErrorMessageLog.Visible = true;
                tbErrorMessageLog.Text = "Error happend...\n" + ex.Message;
            }
        }

        protected void tvUrls_OnNodeClick(object sender, RadTreeNodeEventArgs e)
        {
            object objSelectedUrl = ModuleSettings["SP_SELECTEDURL"];
            if (objSelectedUrl != null)
            {
                if (tvUrls.FindNodeByValue(objSelectedUrl.ToString()) != null)
                    tvUrls.FindNodeByValue(objSelectedUrl.ToString()).ForeColor = System.Drawing.Color.Black;
            }
        }

        private string GetMainUrl()
        {
            return tbSPMainUrl.Text.TrimEnd();
        }

        private string GetDomain()
        {
            return tbDomain.Text.TrimEnd();
        }

        private string GetPassword()
        {
            return tbPassword.Text.TrimEnd();
        }

        private string GetUserName()
        {
            return tbUserName.Text.TrimEnd();
        }

        private string GetInputUrl()
        {
            return tbInputSPUrl.Text.TrimEnd();
        }

        protected void btnInputUrl_OnClick(object sender, EventArgs e)
        {
            panelExistingUrls.Visible = false;
            panelInputUrl.Visible = true;
        }

        /// <summary>
        /// Test whether given url contains document libraries or not
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void btnTestInputUrl_OnClick(object sender, EventArgs e)
        {
            try
            {
                NetworkCredential networkCredential = new NetworkCredential(GetUserName(), GetPassword(), GetDomain());
                string inputUrl = GetInputUrl();
                ModuleController controller = new ModuleController();
                controller.UpdateModuleSetting(this.ModuleId, "SP_INPUTURL", inputUrl);
                int numDocumentLibraries = HasDocumentLibraries(networkCredential, inputUrl);
                tbStatus.Text = inputUrl + " has: " + numDocumentLibraries.ToString() + " Document Libraries";
            }
            catch (Exception ex)
            {
                tbStatus.Text = "Error message: " + ex.Message;
            }
        }

        protected void btnExistingSubsites_OnClick(object sender, EventArgs e)
        {
            panelExistingUrls.Visible = true;
            panelInputUrl.Visible = false;
        }

        protected void btnTestMainUrl_OnClick(object sender, EventArgs e)
        {
            try
            {
                NetworkCredential networkCredential = new NetworkCredential(GetUserName(), GetPassword(), GetDomain());
                HasDocumentLibraries(networkCredential, GetMainUrl());
                tbPassword.Attributes.Add("Value", GetPassword());
                // no error here
                imgMainUrlStatus.ImageUrl = "Images/greenGrant.png";
                imgMainUrlStatus.Visible = true;
                btnTestMainUrl.Text = "Test Url";
            }
            catch 
            {
                //error happened
                tbPassword.Attributes.Add("Value", GetPassword());
                imgMainUrlStatus.ImageUrl = "Images/redError.png";
                imgMainUrlStatus.Visible = true;
                btnTestMainUrl.Text = "Try again";
            }
        }
    }
}